using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Web;
using Microsoft.ReportingServices.Interfaces;
using AUSRIS.Framework.Logging;
using AUSRIS.Reports.Extensions.Security.Authorization;

namespace AUSRIS.Reports.Extensions.Security.Authentication
{
    public class AuthenticationExtension : IAuthenticationExtension
    {
        #region Private Fields

        private ISecurityProvider securityProvider;

        #endregion

        #region Constructor(s)

        public AuthenticationExtension()
        {
            this.securityProvider = ProviderFactory.GetProvider<ISecurityProvider>();
        }

        #endregion

        #region IAuthenticationExtension Members

        /// <summary>
        /// Required by IAuthenticationExtension. The report server calls the 
        /// GetUserInfo methodfor each request to retrieve the current user 
        /// identity.
        /// </summary>
        /// <param name="userIdentity">
        /// Represents the identity of the current user. 
        /// The value of IIdentity may appear in a user interface and 
        /// should be human readable
        /// </param>
        /// <param name="userId">represents a pointer to a unique user identity
        /// </param>
        public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)
        {
#if DEBUG
			Log.Debug(Log.GetSource(), "Getting User Info");
#endif
            try
            {
                //If the current user identity is not null, set the userIdentity parameter to the current user
                if(HttpContext.Current != null && HttpContext.Current.User != null)
                {
                    userIdentity = HttpContext.Current.User.Identity;
                }
                else
                {
                    userIdentity = new GenericIdentity(string.Empty);
                }
            }
            catch(Exception ex)
            {
                userIdentity = new GenericIdentity(string.Empty);
#if DEBUG
				Log.Fatal(Log.GetSource(), ex.ToString());
#endif
            }

            //Initialize a pointer to the current user id to zero
            userId = IntPtr.Zero;
        }

        /// <summary>
        /// The IsValidPrincipalName method is called by the report server when 
        /// the report server sets security on an item. This method validates 
        /// that the user name is valid for Windows.The principal name needs to 
        /// be a user, group, or builtin account name.
        /// </summary>
        /// <param name="principalName">
        /// A user, group, or built-in account name
        /// </param>
        /// <returns>true when the principle name is valid</returns>
        public bool IsValidPrincipalName(string principalName)
        {
#if DEBUG
			Log.Debug(Log.GetSource(), "principalName: {0}", principalName);
#endif
            return this.securityProvider.IsValidPrincipalName(principalName);
        }

        /// <summary>
        /// Indicates whether a supplied username and password are valid.
        /// </summary>
        /// <param name="userName">The supplied username</param>
        /// <param name="password">The supplied password</param>
        /// <param name="authority">
        /// Optional. The specific authority to use to
        /// authenticate a user. For example, in Windows it would be a Windows 
        /// Domain
        /// </param>
        /// <returns>true when the username and password are valid</returns>
        public bool LogonUser(string userName, string password, string authority)
        {
#if DEBUG
			Log.Debug(Log.GetSource(), "userName: {0}, password: {1}, authority: {2}", userName, password ?? "", authority);
#endif
            return this.securityProvider.IsValidCredentials(userName, password, authority);
        }

        #endregion

        #region IExtension Members

        /// <summary>
        /// Required by IExtension
        /// </summary>
        public string LocalizedName
        {
            get
            {
                return null;
            }
        }

        /// <summary>
        /// Required by IExtension
        /// </summary>
        /// <param name="configuration">
        /// Configuration data as an XML string that is stored along with the Extension element in
        /// the configuration file.
        /// </param>
        public void SetConfiguration(string configuration)
        {
            //TODO: read any required config information from xml
        }

        #endregion
    }
}
